package com.innotek.testworkstation.util;

import lombok.extern.slf4j.Slf4j;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName ConcurrentHashMapCacheUtils
 * @Description 本地缓存 工具类;以队列的形式保存缓存，先进先出(FIFO)
 * @Author wangx
 * @Date 2020/4/28 15:02
 * @Version 1.0
 **/

@Slf4j
public class ConcurrentHashMapCacheUtils {
    /**
     * 缓存最大个数
     */
    private static final Integer maxSize = 10;

    /**
     * 当前缓存个数
     */
    private static Integer currentSize = 0;

    /**
     * 缓存对象
     */
    private static ConcurrentHashMap<String, Long> cacheMap = new ConcurrentHashMap<String, Long>();
    /**
     * 这个记录了缓存使用的最后一次的记录，最近使用的在最前面
     */
    private static LinkedList<String> cacheLink = new LinkedList<String>();



    /**
     * 设置缓存
     */
    public static void setCache(String cacheKey, Long expireTime) {
        checkSize(expireTime);
        cacheMap.put(cacheKey, System.currentTimeMillis());
        cacheLink.push(cacheKey);
        currentSize = currentSize + 1;
    }



    /**
     * 判断缓存在不在,过没过期
     */
    public static boolean checkCache(String cacheKey, Long expireTime) {
        expireTime = expireTime *1000;
        if(cacheMap.containsKey(cacheKey)){
            Long time = cacheMap.get(cacheKey);
            if(time==null){
                return false;
            }else {
                if ((time + expireTime ) < System.currentTimeMillis()){
                    // 过期
                    deleteCache(cacheKey);
                    return false;
                }
            }
        }else{
            // 不存在key，返回false
            return false;
        }
        return true;
    }

    /**
     * 删除某个缓存
     */
    public static void deleteCache(String cacheKey) {
        Long cacheValue = cacheMap.remove(cacheKey);
        if (cacheValue != null) {
            cacheLink.remove(cacheKey);
            currentSize = currentSize - 1;
        }
    }

    /**
     * 删除最近最久未使用的缓存
     */
    private static void deleteLastCache() {
        String key = cacheLink.pollLast();
        if(key!=null){
            cacheMap.remove(key);
            currentSize = currentSize - 1;
        }
    }


    /**
     * 检查大小
     * 当当前大小如果已经达到最大大小
     * 首先删除过期缓存，如果过期缓存删除过后还是达到最大缓存数目
     * 删除最久未使用缓存(第一个)
     */
    private static void checkSize(Long time) {
        if (currentSize >= maxSize) {
            deleteTimeOut(time);
        }
        if (currentSize >= maxSize) {
            deleteLastCache();
        }
    }

    public static void result() {
        System.out.println("currentSize:"+currentSize + "; cacheMap: "+ cacheMap.toString());
    }



    /**
     * 批量删除过期的缓存
     */
    private static void deleteTimeOut(Long expireTime) {
        log.info("delete cache time out run!");
        expireTime = expireTime * 1000;
        List<String> deleteKeyList = new LinkedList<String>();
        for(Map.Entry<String, Long> entry : cacheMap.entrySet()) {
            if (entry.getValue() + expireTime < System.currentTimeMillis()) {
                deleteKeyList.add(entry.getKey());
            }
        }
        for (String deleteKey : deleteKeyList) {
            deleteCache(deleteKey);
        }
    }

}
